package com.example.sbbsec;

import com.example.sbbsec.domain.pay.entity.WxPayNotify;
import com.example.sbbsec.domain.pay.entity.WxPayRequest;
import com.example.sbbsec.domain.pay.entity.WxPayResponse;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.google.common.collect.Maps.newHashMap;

/**
 * <p> xml 实体 map 转换工具类
 *
 * @author lowe.yang on 2018-08-30
 */
public class ConvertUtil {
    private ConvertUtil() {
    }

    private static final Logger LOGGER = LoggerFactory.getLogger(ConvertUtil.class);

    /**
     * 对象转xml
     *
     * @param obj 对象
     * @return xml字符串
     */
    public static String objToXml(Object obj) {
        //创建解析XML对象
        final XStream xStream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("_-", "_")));
        //处理注解
        xStream.processAnnotations(obj.getClass());
        return xStream.toXML(obj);
    }

    /**
     * xml 转对象
     *
     * @param xml   xml字符串
     * @param clazz 对象类型
     * @param <T>   泛型
     * @return 对象
     */
    public static <T> T xmlToObj(String xml, Class<T> clazz) {
        //创建解析XML对象
        final XStream xStream = new XStream(new DomDriver());

        //XStream.setupDefaultSecurity(xStream);
        xStream.allowTypes(new Class[]{WxPayNotify.class, WxPayRequest.class, WxPayResponse.class});
        //处理注解
        xStream.processAnnotations(clazz);
        //将XML字符串转为bean对象
        @SuppressWarnings("unchecked") final T t = (T) xStream.fromXML(xml);
        return t;
    }

    /**
     * 对象转map
     *
     * @param obj 对象
     * @return xml字符串
     */
    public static Map<String, Object> objToMap(Object obj) {
        //实体对象转xml 后 再转map
        return xmlToMap(objToXml(obj));
    }

    /**
     * Xml string转换成Map
     *
     * @param xmlStr xml字符串
     * @return 结果map
     */
    public static Map<String, Object> xmlToMap(String xmlStr) {
        try {
            final Document doc = DocumentHelper.parseText(xmlStr);
            final Element el = doc.getRootElement();
            return recGetXmlElementValue(el, new HashMap<String, Object>());
        } catch (DocumentException e) {
            LOGGER.error("获取节点失败:{}", e);
            return newHashMap();
        }
    }

    /**
     * 循环解析xml
     *
     * @param ele 节点原色
     * @param map 结果map
     * @return 返回结果
     */
    @SuppressWarnings({"unchecked"})
    private static Map<String, Object> recGetXmlElementValue(Element ele, Map<String, Object> map) {
        final List<Element> eleList = (List<Element>) ele.elements();
        if (eleList.isEmpty()) {
            map.put(ele.getName(), ele.getTextTrim());
            return map;
        } else {
            for (Element innerEle : eleList) {
                recGetXmlElementValue(innerEle, map);
            }
            return map;
        }
    }

}
